#define LOCAL_CONFIG
#  include "proj_config.h"
#undef LOCAL_CONFIG

#include "util.h"

#include <tiros/tiros.h>


/* Task priorities 
* T[0]  :  1
* T[1]  :  5
* T[2]  :  9
* T[3]  : 13
* Synchro_task_prio : 17
* Idle task : 21
* tmp_task1 : 
*/

/* Priorities */
#define M1_PRIO   2   /* Used by mutex_test */
#define M2_PRIO   4   /* Used by mutex_test */

#define M_TMPTASK2  6 /* Used by task_test */
#define TMP1_TASK_PRIO 3
#define TMP2_TASK_PRIO 8
#define TMP3_TASK_PRIO 7

#define M_PRIO_TEST_TMP   7  /* used for priority test */
#define PRIO_TEST_T1_TMP  0  /* used for priority test */
#define PRIO_TEST_T2_TMP  8  /* used for priority test */

#define M_MAXTST_0 8
#define M_MAXTST_1 7
#define M_MAXTST_2 6



  
#define STKSIZE             (TIROS_MIN_CTXT_SZ + 64)


/* Event flag used for synchronizing all tasks */
static eflag_t  synchro_eflag;
static csem_t synchro_cs;

#define TEST_BEGIN  0x01

static tid_t task_prio;





/* Stacks for each of our tasks */
static osword_t task_stack[NUM_PREDEFINED_TASKS][STKSIZE];

void platform_init(void);
void platform_call_ISR(void);


#define CSEM_TEST 	0
#define EFLAG_TEST 	1
#define MQ_TEST 	2
#define MUTEX_TEST 	3
#define TASK_TEST 	4
#define PRIO_TEST	5
#define TIME_TEST	6

static void csem_test(tid_t taskid);
static void eflag_test(tid_t taskid);
static void mq_test(tid_t taskid);
static void mutex_test(tid_t taskid);
static void task_test(tid_t taskid);
static void prio_test(tid_t taskid);
static void time_test(tid_t taskid);


static void isr_csem_test(int action);
static void isr_eflag_test(int action);
static void isr_mq_test(int action);
static void isr_mutex_test(int action );
static void isr_task_test( int action);
static void isr_prio_test(int action);
static void isr_time_test(int action);

static void wait(void)
{
	delayms(1000);
}



#ifdef TEST_ISR_BASED_CODE

static int isr_test_num;
static int isr_action_num;
static void call_ISR(int const test_num, int const action_num)
{
	isr_test_num = test_num;
	isr_action_num = action_num;
	platform_call_ISR();
	wait();
}





void isr_action(void)
{
	switch(isr_test_num) {

	case CSEM_TEST:
		isr_csem_test(isr_action_num);
		break;
	case EFLAG_TEST:
		isr_eflag_test(isr_action_num);
		break;
	case MQ_TEST:
		isr_mq_test(isr_action_num);
		break;
	case MUTEX_TEST:
		isr_mutex_test(isr_action_num);
		break;
	case TASK_TEST:
		isr_task_test(isr_action_num);
		break;
	case PRIO_TEST:
		isr_prio_test(isr_action_num);
		break;
	case TIME_TEST:
		isr_time_test(isr_action_num);
		break;		
	default:
		break;
	}
}
#endif





static void task_assert( int check_arg, char const * tst_name, 
			 char const * msg,  int16_t argval)
{
	tid_t myid;
	if ( check_arg)
		return;
	myid = os_self_tid();
	putstring(tst_name);
	putstring(" Task:");
	puthexchar(myid);
	putstring("\t");
	putstring(msg); putchar(':');
	puthexshort( (uint16_t)argval);
	putchar('\n');
}


static void synchro_task(void *dummy);




static void idle_task(void *arg)
{
	(void)arg;
	for(;;){
		wait();
	}
}

static void drawline(void)
{
	int i;
	for(i=0; i < 80; i++)
		putchar('-');
	putchar('\n');
}



static void synchro_task(void *arg)
{
	(void) arg;

	putstring("synchro_task\n");
	wait();

	for(;;) {		

		putchar('\n'); 	drawline();
		putstring("Starting Test 0\n");  wait(); wait(); wait();
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);	
		(void) csem_P(&synchro_cs, 0, 0);

		putchar('\n'); 	drawline();
		putstring("Starting Test 1\n");  
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);
		(void) csem_P(&synchro_cs, 0, 0);

		putchar('\n'); 	drawline();
		putstring("Starting Test 2\n");  wait();
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);	
		(void) csem_P(&synchro_cs, 0, 0);

		putchar('\n'); 	drawline();
		putstring("Starting Test 3\n");  wait();
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);
		(void) csem_P(&synchro_cs, 0, 0);

		putchar('\n'); 	drawline();
		putstring("Starting Test 4\n");  wait();
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);
		(void) csem_P(&synchro_cs, 0, 0);

		putchar('\n'); 	drawline();
		putstring("Starting Test 5\n");  wait();
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);
		(void) csem_P(&synchro_cs, 0, 0);

		putchar('\n'); 	drawline();
		putstring("Starting Test 6\n");  wait();
		(void)eflag_set(&synchro_eflag, TEST_BEGIN, O_EFLAG_TRIGGER);
		(void) csem_P(&synchro_cs, 0, 0);

	}

}

static void T(void  *arg)
{
	static char const * const err_name = "T synchro_wait";
	int8_t rc;
	tid_t mytid = os_self_tid();
	(void) arg;

	putstring("Task "); puthexchar(mytid); putstring(" starting\n");

	for(;;) {
		/*lint --e{838}  rc is not used before being reassigned */

		/* Wait for task begin flag */
		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		task_assert( (int)(rc == SUCCESS), err_name, 
			     "eflag_wait_failed before csem_test", rc);
		csem_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring(" Done\n");
		
		/* Wait for task begin flag */
		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		task_assert( (int)(rc == SUCCESS), err_name, 
			     "eflag_wait_failed before eflag_test", rc);
		eflag_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring(" Done\n");
	
		/* Wait for task begin flag */
		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		task_assert( (int)(rc == SUCCESS), err_name, 
			     "eflag_wait_failed before mq_test", rc);
		mq_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring("Done\n");

		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		task_assert( (int)(rc == SUCCESS), err_name, 
			     "eflag_wait_failed before mutex_test", rc);
		mutex_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring("Done\n");

		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		if (mytid != 0x03) {
			task_assert( (int)(rc == SUCCESS), err_name, 
				     "eflag_wait_failed before task_test", rc);
		}
		task_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring("Done\n");

		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		task_assert( (int)(rc == SUCCESS), err_name, 
			     "eflag_wait_failed before prio_test", rc);
		prio_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring("Done\n");

		rc = eflag_wait(&synchro_eflag,  TEST_BEGIN, 0, 0);
		task_assert( (int)(rc == SUCCESS), err_name, 
			     "eflag_wait_failed before time_test", rc);
		time_test(mytid);
		putstring("Task: "); puthexchar(mytid); putstring("Done\n");

	}
}


static tid_t Ttid[NUM_WRKR_TASKS];

static void print_ret_code(int8_t rc)
{
	puthexshort( (unsigned short) (uint8_t) rc);
}

int main(void) 
{
	tid_t idle_task_tid;
	tid_t synchro_task_tid;
	int i;

	platform_init();

	/* ------------------------------------------------------------ */
	/* Print out error codes */
	drawline();
	putstring("\nReturn codes");
	drawline();
	putstring("\nSuccess:"); print_ret_code(SUCCESS);
	putstring("\nERR_LOCK:"); print_ret_code(ERR_LOCK);
	putstring("\nERR_LOCK_ISR:"); print_ret_code(ERR_LOCK_ISR);
	putstring("\nERR_LOCK_PRIO_CEIL:"); print_ret_code(ERR_LOCK_PRIO_CEIL);
	putstring("\nERR_WOULDBLOCK:"); print_ret_code(ERR_WOULDBLOCK);
	putstring("\nERR_WOULDBLOCK_ISR:"); print_ret_code(ERR_WOULDBLOCK_ISR);
	putstring("\nERR_WOULDBLOCK_MUTEX:"); print_ret_code(ERR_WOULDBLOCK_MUTEX);
	putstring("\nERR_FULL:"); print_ret_code(ERR_FULL);
	putstring("\nERR_NOTOWNER:"); print_ret_code(ERR_NOTOWNER);
	putstring("\nERR_TIMEOUT:"); print_ret_code(ERR_TIMEOUT);
	putstring("\nERR_RESUMED:"); print_ret_code(ERR_RESUMED);
	putstring("\nERR_NOSUCHTASK:"); print_ret_code(ERR_NOSUCHTASK);
	putstring("\nERR_TASKBLOCKED:"); print_ret_code(ERR_TASKBLOCKED);
	putstring("\nERR_PRIO_IN_USE:"); print_ret_code(ERR_PRIO_IN_USE);
	putstring("\nERR_FAILED:"); print_ret_code(ERR_FAILED);
	putchar('\n');

	drawline();
	/* -------------------------------------------------- */
	os_init();
	task_prio = 1;

	/* Tasks have prio:  1, 5, 9, 13 */
	for(i=0; i < NUM_WRKR_TASKS; i++) {
		Ttid[i] = os_task_create(T, (osptr_t)0,
					 task_stack[i], STKSIZE, task_prio); 
		task_prio += 4;

		if (Ttid[i] == ILLEGAL_ELEM) {
			putstring("Task create failed");
		}
	}



	/* Start synchro task from here to get full code coverage */
	synchro_task_tid = os_task_create(synchro_task, (osptr_t)0,
			       task_stack[NUM_WRKR_TASKS], STKSIZE, task_prio); 

	if (synchro_task_tid == ILLEGAL_ELEM  ) {
		putstring("Error creating synchro/idle task\n");
	}



	task_prio += 4;
	idle_task_tid = os_task_create(idle_task, (osptr_t)0,
			       task_stack[NUM_WRKR_TASKS+1], STKSIZE, task_prio); 
	/* Synchro task is started next.  It has higher priority */

	if ( idle_task_tid == ILLEGAL_ELEM) {
		putstring("Error creating idle task\n");
	}

	eflag_init(&synchro_eflag, 0);
	csem_init(&synchro_cs, 0, TIROS_CSEMVAL_MAX);



	os_start();
	putstring("Started OS: Shouldn't reach here\n");

	for(;;) {   	}
}




#define ISR_CSEM_TEST1 0x01
#define ISR_CSEM_TEST2 0x02


static  csem_t isr_cs1;
static  csem_t isr_cs2;

#ifdef TEST_NESTED_ISRS
extern uint8_t os_isr_nesting;
#endif

static void isr_csem_test(int action)
{
	static char const * const test_name = "isr_csem_test";
	int16_t rc;
	switch(action) {
	case ISR_CSEM_TEST1:
		rc = csem_P(&isr_cs1, 0, O_NONBLOCKING);
		task_assert((int)(rc == ERR_WOULDBLOCK), test_name,
			    "bad retval non-blocking csem_P from isr",
			    rc);
		

		rc = csem_P(&isr_cs1, 0, 0);
		task_assert((int)(rc == ERR_WOULDBLOCK_ISR), test_name,
			    "bad retval blocking csem_P from isr", rc);
		
		rc = csem_V(&isr_cs1);
		task_assert((int)(rc == 1), test_name,
			    "csem_V[0] from isr did not succeed", rc);

#ifdef TEST_NESTED_ISRS
		if (os_isr_nesting < TIROS_MAX_ISR_NESTING) {
			OS_INT_ENABLE();
			putstring("csem_isr_test1 calling ISR\n");
			call_ISR(CSEM_TEST, ISR_CSEM_TEST2);
		}
		putstring("csem_isr_test1 done calling ISR\n");
		
#endif

		break;

	case ISR_CSEM_TEST2:
#ifdef TEST_NESTED_ISRS
		putstring("csem_isr_test2 got called\n");
		rc = csem_V(&isr_cs2);
		task_assert((int)(rc == 1), test_name,
			    "csem_V[1] from isr did not succeed", rc);
#endif
		break;
	default:
		task_assert(0, test_name, "No such test", action);
	}

}




static void csem_test(tid_t taskid)
{
	static csem_t common_cs;
	static char const * const test_name = "csem_test";
	csem_t tst_cs;
	int i;
	int16_t rc;
	trtime_t timeoutval;

	if (taskid == Ttid[0]) {

		/* First task to run */
		csem_init(&common_cs, 1, TIROS_CSEMVAL_MAX-2);

		csem_init(&common_cs, 1, TIROS_CSEMVAL_MAX);
		rc = csem_count(&common_cs);
		task_assert((int)(rc == 1),test_name, 
			    "csem_count wrong after init", rc);


		/* Perform a P */
		rc = csem_P(&common_cs, 0, O_NONBLOCKING);
		task_assert((int)(rc == 0), test_name,
			    "P[0] wrong ret", rc);
			    
		/* Perform a P with no timeout */
		rc = csem_P(&common_cs, 0, 0);
		task_assert((int)(rc == 0), test_name, 
			    "P[1] failed", rc);

		/* Keep doing a csem_V until it hits max value */
		csem_init(&tst_cs, 0,  TIROS_CSEMVAL_MAX);
		for (i=0; i<TIROS_CSEMVAL_MAX; i++)
			(void)csem_V(&tst_cs);


		(void)csem_V(&tst_cs);
		rc = csem_V(&tst_cs);

		task_assert((int)(rc == ERR_FULL), test_name,
			     "csem_V beyond max gave wrong retcode", rc);



	} else if (taskid == Ttid[1]) {



		/* Perform P with non-blocking option */
		rc = csem_P(&common_cs, 0, O_NONBLOCKING);
		task_assert((int)(rc == ERR_WOULDBLOCK), test_name,
			    "P[0] failed", rc);

#ifdef TEST_ISR_BASED_CODE
		csem_init(&isr_cs1, 0, TIROS_CSEMVAL_MAX);
		csem_init(&isr_cs2, 0, TIROS_CSEMVAL_MAX);
		rc = csem_P(&isr_cs1, 0, 0);
		task_assert((int)( rc == 0), test_name,
			     "P[1] failed", rc);
#endif


	} else if (taskid == Ttid[2]) {

#ifdef TEST_ISR_BASED_CODE

		call_ISR(CSEM_TEST, ISR_CSEM_TEST1);

#endif


		/* Perform P with timeout */
		secs_to_trtime(1LU, &timeoutval);
		rc = csem_P(&common_cs, &timeoutval, 0);
		task_assert((int)(rc == ERR_TIMEOUT), test_name,
			    "P[0] failed", rc);

	} else if (taskid == Ttid[3]) {
		/* Perform a V */
		secs_to_trtime(2LU, &timeoutval);
		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);
		task_assert((int)(rc == SUCCESS), test_name,
			    "wake_at failed", rc);
		rc = csem_V(&common_cs);
		task_assert((int)(rc == 1), test_name,
			    "V[0] failed", rc);


#ifdef  TEST_ISR_BASED_CODE
#ifdef  TEST_NESTED_ISRS
		rc = csem_P(&isr_cs2, 0, 0);
		task_assert((int)(rc == 0), test_name,
			    "P[0] failed", rc);
#endif
#endif


		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V[1] failed", rc);
	} else {

	}
	

}



#define COMMON_FLAG1 0x04
#define COMMON_FLAG2 0x08

static void eflag_test(tid_t taskid)
{
	static eflag_t common_ef;
	static char const * const test_name = "eflag_test";
	trtime_t timeoutval;
	flag_t tmp;
	int8_t rc;

	if (taskid == Ttid[0]) {
		/* First task to run */
		eflag_init(&common_ef, 0);

		(void)eflag_set(&common_ef, COMMON_FLAG2, 0);
		tmp = eflag_get(&common_ef);
		task_assert((int)(tmp == COMMON_FLAG2), test_name, 
			    "Get[0] failed", (int16_t) tmp);

		/* Perform a wait with no timeout */
		rc = eflag_wait(&common_ef, COMMON_FLAG2, 0, O_EFLAG_OR);
		task_assert((int)(rc == SUCCESS), test_name,
			    "W[0] failed", rc);

		/* Perform a wait with no timeout */
		rc = eflag_wait(&common_ef, COMMON_FLAG1, 0, O_EFLAG_AND);
		task_assert((int)(rc == SUCCESS), test_name,
			    "W[1] failed", rc);

	} else if (taskid == Ttid[1]) {
		/* Perform wait with non-blocking option */
		rc = eflag_wait(&common_ef, COMMON_FLAG1, 0, 
				O_EFLAG_OR | O_NONBLOCKING);
		task_assert((int)(rc == ERR_WOULDBLOCK), test_name,
			    "W[0] failed", rc);

		/* Perform wait with non-blocking option */
		rc = eflag_wait(&common_ef, COMMON_FLAG1, 0, O_EFLAG_OR);
		task_assert((int)(rc == SUCCESS), test_name,
			    "W[1] failed", rc);

	} else if (taskid == Ttid[2]) {
		/* Perform wait with timeout */
		secs_to_trtime(1LU, &timeoutval);
		rc = eflag_wait(&common_ef, COMMON_FLAG1, &timeoutval,
				O_RELATIVE_TIME| O_EFLAG_OR);
		task_assert((int)(rc == ERR_TIMEOUT), test_name,
			    "W[0] failed", rc);

	} else if (taskid == Ttid[3]) {
		/* Set flag */
		secs_to_trtime(2LU, &timeoutval);		
		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);
		task_assert((int)(rc == SUCCESS), test_name,
			    "wake_at[0] failed", rc);

		(void)eflag_set(&common_ef, COMMON_FLAG1, O_EFLAG_CLEAR);
		
		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);
		task_assert((int)(rc == SUCCESS), test_name,
			    "wake_at[1] failed", rc);

		(void) eflag_set(&common_ef, COMMON_FLAG1, O_EFLAG_TRIGGER);

		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V[0] failed", rc);


	} else {

	}


}


static void isr_eflag_test(int action)
{
	(void)action;
}






#define COMMON_MQ_SZ    4

static void mq_test(tid_t taskid)
{
	static char const * const test_name = "mq_test";
	static osword_t common_mq_mem[msgQ_MEMSZ(COMMON_MQ_SZ)];
	trtime_t timeoutval;
	int8_t rc;
	int i;
	osptr_t tmp;

	msgQ_t * common_mq = msgQ_mem2ptr(common_mq_mem);
	
	if (taskid == Ttid[0]) {
		/* First task to run */
		msgQ_init(common_mq, COMMON_MQ_SZ);


		rc = msgQ_send(common_mq, (osptr_t)(osptrword_t)9);
		task_assert((int)(rc == SUCCESS), test_name,
			    "send[0] failed", rc);


		rc = msgQ_recv(common_mq, 0, O_NONBLOCKING, &tmp);
		task_assert((int) (rc == SUCCESS), test_name,
			     "recv[0] failed", rc);
		
		task_assert((int)((osword_t)tmp == 9), test_name,
			    "recv[1] wrong val", (int16_t)(osword_t)tmp);


		/* Perform post fully */
		for(i=0; i< COMMON_MQ_SZ; i++) {
			rc = msgQ_send(common_mq, (osptr_t)(osptrword_t)i);
			task_assert((int)(rc == SUCCESS), test_name,
				    "send[0] failed", rc);
			rc = (int8_t) msgQ_count(common_mq);
			task_assert((int)(rc == (i+1)), test_name,
				    "mQ Count wrong", rc);
		}
		
		rc = msgQ_send(common_mq, (osptr_t)(osptrword_t)i);
		task_assert((int)(rc == ERR_FULL), test_name,
			    "send[1] failed", rc);
		rc = (int8_t)msgQ_count(common_mq);
		task_assert((int)(rc == COMMON_MQ_SZ), test_name,
			    "mQ Count wrong", rc);

		
		/* Retrieve all messages back out */
		for(i=0; i<COMMON_MQ_SZ; i++) {
			rc = msgQ_recv( common_mq, 0,
					O_NONBLOCKING, &tmp);

			task_assert((int)( rc == SUCCESS), test_name,
				     "recv[2] failed", rc);
			task_assert((int)( (int)tmp == i), test_name,
				    "recv[2] wrong ret", (int16_t)(osword_t)tmp);
		}

		for (i=0; i<COMMON_MQ_SZ; i++) {
			rc = msgQ_recv( common_mq, 0,0 , &tmp);
			task_assert((int)(rc == SUCCESS), test_name,
				    "recv[3] failed", rc);
		}
		task_assert((int)((int)tmp == 7), test_name,
			    "recv[4] wrong val", (int16_t)(osword_t)tmp);
		
		

		/* Done */
	} else if (taskid == Ttid[1]) {
		/* Perform wait with non-blocking option */
		rc = msgQ_recv(common_mq, 0, O_NONBLOCKING, &tmp);
		task_assert((int)(rc == ERR_WOULDBLOCK), test_name,
			    "recv[0] failed", rc);


	} else if (taskid == Ttid[2]) {
		/* Perform wait with timeout */
		secs_to_trtime(1LU, &timeoutval);
		rc = msgQ_recv(common_mq, &timeoutval, 0, &tmp);
		task_assert((int)(rc == ERR_TIMEOUT), test_name,
			     "recv[0] failed", rc);

	} else if (taskid == Ttid[3]) {
		/* Set flag */
		secs_to_trtime(2LU, &timeoutval);		
		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "wake_at[0] failed", rc);

		for(i=0; i<COMMON_MQ_SZ; i++) {
			rc = msgQ_send(common_mq, (osptr_t)(osptrword_t)7);
			task_assert((int)(rc == SUCCESS), test_name,
				    "send[0] failed", rc);
		}

		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V[0] failed", rc);


	} else {

	}


}

static void isr_mq_test(int action)
{
	(void) action;
}










/* The sequence of events is as follows:
 * Task 0, initializes mutexes.
 * Task 0 attempts to lock m2.  This fails due to the priority ceiling
 * rule.
 * Task 0 is complete.
 * Task 1 runs and sleeps for 1 sec, then waits for signal from Task 3
 * Task 2 runs and exercises tests on mutexes m[0] to m[2].
 * Task 2 waits for task3 to signal with csem.
 * Task 3 runs and locks m2 successfully.
 * Task 3 locks m2 again (returns success).
 ** Task 3 signals Task 2 with csem.
 ** Task 2 locks m1 successfully.
 ** Task 2 locks m2. This succeeds with the priority inheritance protocol and fails
 **    if the default priority ceiling protocol is used.
 * Task 2 unlocks m1 successfully.
 * TAsk 3 signals Task 1.  (but Task1 may still be sleeping)
 * * Task 1 awakes.
 * Task 1 locks m1 successfully.
 * Task 1 unlocks m1 successfully.
 * Task 1 is done.
 *   Task 3 attempts to sleep for 3 secs.
 * #If TIROS_ALLOW_SLEEP_W_MUTEX == 1.
 *    Task 3 sleeps.
 * #else If TIROS_ALLOW_SLEEP_W_MUTEX is 0 (default)
 *    Task 3 is not allowed to sleep.
 * #endif
 *    Task 3 unlocks m2.
 *    Task 3 unlocks m2 again.
 *    Task 3 sleeps for 3 secs.
 *    Task 3 wakes and is done.
 */

#define ISR_MUTEX_TEST1  0x01

static mutex_t isr_mutex_try;
static void isr_mutex_test(int action)
{
	static char const * const test_name = "mutex_isr";
	int16_t rc;
	switch(action) {
	case ISR_MUTEX_TEST1:
		mutex_init(&isr_mutex_try, M1_PRIO);
		rc = mutex_lock(&isr_mutex_try,  0, O_NONBLOCKING);
		task_assert((int)(rc == ERR_LOCK_ISR), test_name,
			    "bad retval for isr mutex_lock", rc);
		break;

	default:
		task_assert( 0, test_name,
			    "bad action", action);

		break;
	}

}





static void mutex_test(tid_t taskid)
{
	static char const * const test_name = "mutex_test";
	static csem_t  t3_t1_sig;
	static csem_t  t3_t2_sig;
	static mutex_t m1;
	static mutex_t m2;
	static mutex_t m[TIROS_MAX_MUTEXES+1];
	tid_t owner;
	trtime_t timeoutval, currtime;
	int8_t rc;

	if (taskid == Ttid[0]) {
		mutex_init(&m1, M1_PRIO);
		mutex_init(&m2, M2_PRIO);
		csem_init(&t3_t1_sig, 0, 1);
		csem_init(&t3_t2_sig, 0, 1);

		call_ISR(MUTEX_TEST, ISR_MUTEX_TEST1);
		rc = mutex_lock(&m2, 0, O_NONBLOCKING);

		task_assert((int)( rc == ERR_LOCK_PRIO_CEIL), test_name,
			     "lock[0] wrong ret", rc);
		
	} else if (taskid == Ttid[1]) {
		timeoutval.units = 0; timeoutval.subunits = 0;
		secs_to_trtime(1LU, &timeoutval);

		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);
		task_assert((int)(rc == SUCCESS), test_name,
			    "wake[0] failed", rc);

		os_time_get(&currtime);
		time_add(&currtime, &timeoutval, &timeoutval);


		


		rc = mutex_lock(&m2, 0, O_NONBLOCKING);
		task_assert((int)(rc == ERR_WOULDBLOCK), test_name,
			    "Lock[2] wrong ret", rc);
		rc = mutex_lock(&m2, 0, 0);
		/* If priority ceiling protocol is used, Task 2 will 
		   be running at a higher priority than Task 1 and
		   this point will only be reached when Task 2 has
		   given up its mutexes. */
		task_assert((int)(rc == SUCCESS), test_name,
			    "Lock[2] failed", rc);
		rc = mutex_unlock(&m2);
		task_assert((int)(rc == SUCCESS), test_name,
			    "UnLock[2] failed", rc);
		

		


		rc = csem_P(&t3_t1_sig, 0, 0);
		task_assert((int)(rc == 0), test_name,
			    "csem_P failed", rc);


		/* Lock again without timeout */
		rc = mutex_lock(&m1, 0, 0);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Lock[4] failed", rc);
		
		/* Unlock */
		rc = mutex_unlock(&m1);
		task_assert((int)(rc == SUCCESS), test_name,
			    "UnLock[0] failed", rc);


	} else if (taskid == Ttid[2]) {
		/* Test to lock beyond max allowed mutexes */
		mutex_init(&m[0], M_MAXTST_0);
		mutex_init(&m[1], M_MAXTST_1);
		mutex_init(&m[2], M_MAXTST_2);

		
		rc = mutex_lock(&m[0], 0, O_NONBLOCKING);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "Lock[0] failed", rc);
		

		rc = mutex_lock(&m[1], 0, O_NONBLOCKING);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "Lock[1] failed", rc);

		rc = mutex_lock(&m[2], 0, O_NONBLOCKING);
		task_assert((int)(rc == ERR_FULL), test_name, 
			    "Lock[2] wrong ret", rc);
		
		rc = mutex_unlock(&m[2]);
		task_assert((int)(rc == ERR_NOTOWNER), test_name,
			    "Unlock[0] wrong ret", rc);

		rc = mutex_unlock(&m[1]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[1] wrong ret", rc);


		rc = mutex_unlock(&m[0]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[2] wrong ret", rc);
		

		rc = mutex_lock(&m[0], 0, O_NONBLOCKING);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "Lock[3] failed", rc);

		rc = mutex_lock(&m[0], 0, O_NONBLOCKING);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "Lock[4] failed", rc);

		rc = mutex_unlock(&m[0]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[2] wrong ret", rc);

		
		/* This task should still be the owner */
		owner = mutex_owner(&m[0]);
		task_assert((int)(owner == Ttid[2]), test_name,
			    "Wrong owner after single unlock of double locked mutex", rc);
		
		rc = mutex_unlock(&m[0]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[3] wrong ret", rc);



		rc = csem_P(&t3_t2_sig, 0, 0);
		task_assert((int)(rc == 0), test_name,
			    "csem_P failed", rc);



		rc = mutex_lock(&m1, 0, 0);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Lock[3] failed", rc);


		rc = mutex_lock(&m2, 0, 0);

		task_assert((int)(rc == ERR_LOCK_PRIO_CEIL), test_name,
			    "Lock[4] bad retval, should be err_prio_ceil", rc);


		rc = mutex_unlock(&m1);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[4] failed", rc);



	} else if (taskid == Ttid[3]) {







		rc = mutex_lock(&m2, 0, O_NONBLOCKING);
		task_assert((int)(rc == SUCCESS), test_name,	
			    "Lock[0] wrong ret", rc);
		owner = mutex_owner(&m2);
		task_assert((int)(owner == Ttid[3]), test_name, 
			    "Locked mutex but not owner", 0);

		rc = mutex_lock(&m2, 0, O_NONBLOCKING);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Lock[1] wrong ret", rc);


		rc = csem_V(&t3_t2_sig);
		task_assert((int)(rc == 1), test_name,
			    "V[0] failed", rc);

		rc = csem_V(&t3_t1_sig);
		task_assert((int)(rc == 1), test_name,
			    "V[1] failed", rc);


		secs_to_trtime(3LU, &timeoutval);
		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);

#if (TIROS_ALLOW_SLEEP_W_MUTEX == 1)
		task_assert((int)(rc == SUCCESS), test_name,
			    "Wake[0] failed", rc);
#else
		task_assert((int)(rc == ERR_WOULDBLOCK_MUTEX), test_name,
			    "Wake[0] failed", rc);
#endif


		rc = mutex_unlock(&m2);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[0] failed", rc);

		owner = mutex_owner(&m2);
		task_assert((int)(owner == Ttid[3]), test_name, 
			    "Unlocked mutex partial recursion but not owner", owner);

		rc = mutex_unlock(&m2);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Unlock[1] wrong ret", rc);


		rc = os_wake_at(&timeoutval, O_RELATIVE_TIME);
		task_assert((int)(rc == SUCCESS), test_name,
			    "Wake[1] failed", rc);

		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V[2] failed", rc);
		

		

	} else {

	}


}




static osword_t tmp_task1_stk[STKSIZE];
static osword_t tmp_task2_stk[STKSIZE];
static osword_t tmp_task3_stk[STKSIZE];
static osword_t dummy_task_stk[STKSIZE];

static tid_t tmp1=ILLEGAL_ELEM, tmp2=ILLEGAL_ELEM, tmp3 = ILLEGAL_ELEM;

static csem_t tmp_task2_tmp_task1;  /* Signal tmp_task1 from tmp_task2 */

#define ISR_TASK_TEST1 0x01
static void isr_task_test(int action)
{
	static char const * const test_name = "task_test_isr";
	tid_t mytid;
	switch (action) {
	case ISR_TASK_TEST1:
		mytid = os_self_tid();
		task_assert((int)( mytid == ILLEGAL_ELEM),  test_name,
			     "os_self_tid bad retval from ISR", mytid);
		break;

	default:
		task_assert(0, test_name, "bad action", (int16_t) action);
		break;
	}

}


static void dummy_task(void *arg)
{
	(void) arg;
	for(;;) {
		wait();
	}
}


static void tmp_task1(void *arg)
{
	tid_t dummy;
	int16_t rc;
	static char const * const test_name = "task_test";
	(void) arg;

	/* This task will self delete. */


	/* Tests 
	 * Create task after TCB table full
	 * Delete illegal task 
	 * Delete task that doesn't exist 
	 * Suspend a task holding a mutex
	 * Delete task holding a mutex 
	 * Delete a task holding a lock 
	 * Self delete */

	
	dummy = os_task_create(dummy_task, (osptr_t)0,
			       dummy_task_stk, STKSIZE,  6);
	task_assert((int)(dummy == ILLEGAL_ELEM), test_name,
		    "os_task_create_0 unexpectedly succeeded", dummy);
		

	rc = os_task_suspend(tmp2);
	task_assert((int)(rc == ERR_TASKBLOCKED), test_name,
		    "should not have suspended tmp_task2", rc);


	rc = os_task_del(tmp2);
	task_assert((int)(rc == ERR_TASKBLOCKED), test_name,
		    "should not have deleted tmp_task2", rc);


	rc = csem_P(&tmp_task2_tmp_task1, 0, 0);
	task_assert((int)(rc == 0), test_name,
		    "got wrong value from csem_P", rc);

	rc = os_task_del(tmp2);
	task_assert((int)(rc == SUCCESS), test_name,
		    "could not delete tmp_task2", rc);


	rc = os_task_del(tmp2);
	task_assert((int)(rc == ERR_NOSUCHTASK), test_name,
		    "unexpectedly redeleted tmp_task2", rc);

	rc = os_task_del(tmp3);
	task_assert((int)(rc == SUCCESS), test_name, 
		    "could not delete tmp_task3", rc);


	dummy = os_self_tid();

	/* Note that at this point, tmp1 does not have a valid
	   value. Since the priority of tmp_task1 is higher than
	   tmp_task2, tmp_task2 got context switched in the middle of
	   creating tmp_task1 and was not done updating the value of
	   tmp1 */
	rc = os_task_del(dummy );
	task_assert(0, test_name, 
		    "tmp_task1 did not delete itself : ", 0);

	for(;;) {
		wait();
	}
}

static void tmp_task3(void  *arg)
{
	(void) arg;

	(void)csem_P(&tmp_task2_tmp_task1, 0, 0);
	/* Should not reach here */
	for(;;) {
		putstring("tmp_task3\n");
		wait();
	}
}

static void tmp_task2(void  *arg)
{
	/* This mutex is not accessed by anyother task, so ok to have
	   local */
	mutex_t tmpmutex2;
	int16_t rc;
	static char const * const test_name = "task_test";
	(void) arg;

	csem_init(&tmp_task2_tmp_task1, 0, TIROS_CSEMVAL_MAX);

	mutex_init(&tmpmutex2, M_TMPTASK2);
	rc = mutex_lock(&tmpmutex2, 0, O_NONBLOCKING);
	task_assert((int)(rc == SUCCESS), test_name,
		    "mutex_lock failed", rc);

	rc = csem_P(&tmp_task2_tmp_task1, 0, 0);
	task_assert((int)(rc == ERR_WOULDBLOCK_MUTEX), test_name,
		    "bad ret val from blocking call with mutex held", rc);


	tmp3 = os_task_create(tmp_task3, (osptr_t)0,
			      tmp_task3_stk, STKSIZE,  TMP3_TASK_PRIO);
	task_assert((int)(tmp3 != ILLEGAL_ELEM), test_name,
		    "os_task_create_0 failed", tmp3);

	
	tmp1 = os_task_create(tmp_task1, (osptr_t)0,
			      tmp_task1_stk, STKSIZE,  TMP1_TASK_PRIO);
	task_assert((int)(tmp1 != ILLEGAL_ELEM), test_name,
		    "os_task_create_2 failed", tmp1);

	rc = mutex_unlock(&tmpmutex2);
	task_assert((int)(rc == SUCCESS), test_name, 
		    "mutex_unlock failed", rc);
		
	rc = csem_V(&tmp_task2_tmp_task1);
	
	

	/* This task will be deleted at this point */

	for(;;) {
		task_assert(0, test_name,
			    "tmp_task2 must not run", 0);
		wait();
	}
}


static void task_test(tid_t taskid)
{	
	int16_t rc;
	static csem_t task_test_csem;
	static char const * const test_name = "task_test";

	/* Task tests 
	 * 1. Create with duplicate priority .
	 * 2. Suspend illegal task  
	 * 3. Suspend task that is waiting on a lock 
	 * 4. Suspend task in ready list 
	 * 5. Resume illegal task 
	 * 6. Resume task waiting on a lock 
	 * 7. Resume task that was suspended */

	if (taskid == Ttid[0]) {

		call_ISR(TASK_TEST, ISR_TASK_TEST1);

		/* Create with illegal priority */
		tmp1 = os_task_create(tmp_task1, (osptr_t)0,
				      tmp_task1_stk, STKSIZE, ILLEGAL_ELEM);
		task_assert((int)(tmp1 == ILLEGAL_ELEM ), test_name, 
			    "os_task_create_0 unexpectedly suceeded", tmp1);			


		/* Create with duplicate priority */
		tmp1 = os_task_create(tmp_task1, (osptr_t)0,
					tmp_task1_stk, STKSIZE, 1);
		task_assert((int)(tmp1 == ILLEGAL_ELEM ), test_name,
			    "os_task_create_1 unexpectedly suceeded", tmp1);
		

		tmp2 = os_task_create(tmp_task2, (osptr_t)0,
				      tmp_task2_stk, STKSIZE,  TMP2_TASK_PRIO);

		task_assert((int)(tmp2 != ILLEGAL_ELEM), test_name,
			    "os_task_create_2 failed", tmp2);


		/* tmp2 is of lower priority, so it should not run
		   just yet. Lets try appropriate actions on the
		   illegal task.  The taskID of (TIROS_MAX_PROCS -1)
		   does not yet exist. */
		rc = os_task_del(ILLEGAL_ELEM);
		task_assert((int)(rc == ERR_NOSUCHTASK), test_name,
			    "delete  nonexistent task bad ret", rc);

	
		rc = os_task_del(TIROS_MAX_PROCS -1);
		task_assert((int)(rc == ERR_NOSUCHTASK), test_name,
			    "succeeded in deleting ILLEGAL_ELEM", rc);

		rc = os_task_suspend(ILLEGAL_ELEM);
		task_assert((int)(rc == ERR_NOSUCHTASK), test_name,
			    "succeeded in suspending ILLEGAL_ELEM", rc);
	
		rc = os_task_suspend( TIROS_MAX_PROCS -1);
		task_assert((int)(rc == ERR_NOSUCHTASK), test_name, 
			    "succeeded in suspending nonexistent task",
			    rc);

		rc = os_task_resume(ILLEGAL_ELEM);
		task_assert((int)(rc == ERR_NOSUCHTASK), test_name,
			    "succeeded in resuming ILLEGAL_ELEM", rc);

		rc = os_task_resume( TIROS_MAX_PROCS -1);
		task_assert((int)(rc == ERR_NOSUCHTASK), test_name, 
			    "succeeded in resuming nonexistent task", rc);

		/* Resume an active task */
		rc = os_task_resume( Ttid[3]);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "failed to resume active task", rc);


		/* Suspend task Ttid[3] */		
		rc = os_task_suspend(Ttid[3]);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "suspend Ttid[3] failed", rc);

		/* Self suspend */
		rc = os_task_suspend(Ttid[0]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "self_suspend failed", rc);
		

	} else if (taskid == Ttid[1]) {
		/* Initialize counting semaphore */
		csem_init(&task_test_csem , 0, TIROS_CSEMVAL_MAX);

		/* Resume task Ttid[3] */
		rc = os_task_resume(Ttid[3]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "resume Ttid[3] failed", rc);

		/* Wait for a lock infinitely until suspend/resume. */		
		rc = csem_P(&task_test_csem, 0, 0);
		task_assert((int)( rc == ERR_RESUMED), test_name, 
			     "Not resumed from infinite wait", rc);

	} else if (taskid == Ttid[2]) {
		/* Suspend task that is waiting on a lock */
		rc = os_task_suspend(Ttid[1]);
		task_assert((int)( rc == SUCCESS), test_name, 
			     "Could not resume Ttid[1]", rc); 
		
		rc = csem_P(&task_test_csem, 0, 0);
		task_assert((int)(rc == ERR_RESUMED), test_name,
			    "Not resumed from infinite wait", rc);

	} else if (taskid == Ttid[3]) {
		/* Resume task Ttid[0] that has self suspended */
		rc = os_task_resume(Ttid[0]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "resume Ttid[0] failed", rc);

		/* Resume task Ttid[1] that was earlier suspended. */
		rc = os_task_resume(Ttid[1]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "resume Ttid[1] failed", rc);
		
		/* Resume task Ttid[2] that is waiting for a lock. */
		rc = os_task_resume(Ttid[2]);
		task_assert((int)(rc == SUCCESS), test_name, 
			    "resume Ttid[2] failed", rc);


		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V_0 failed", rc);

	} 

}



static void prio_test(tid_t taskid)
{
	int16_t rc;
	static char const * const test_name = "prio_test";
	static csem_t prio_test_t2_t0;
	mutex_t prio_test_tmp;
	tid_t t2_orig_prio, t1_orig_prio;

	if (taskid == Ttid[0]) {
		csem_init(&prio_test_t2_t0, 0, TIROS_CSEMVAL_MAX);
		/* prio_get Tests:
		 * 1. ILLEGAL_ELEM
		 * 2. nonexistent task
		 * 3. real priority
		 * 4. effective priority */
		rc = os_prio_get(ILLEGAL_ELEM, 0);
		task_assert((int)( rc == ILLEGAL_ELEM), test_name, 
			     "got prio of illegal task", rc);

		rc = os_prio_get(TIROS_MAX_PROCS-1, 0);
		task_assert((int)( rc == ILLEGAL_ELEM), test_name, 
			     "got prio of nonexistent task", rc);

		
		rc = os_prio_get(Ttid[0], 0);
		task_assert((int)( rc == 1), test_name, 
			     "got wrong prio of self", rc);

		rc = os_prio_get(Ttid[0], O_EFFECTIVE_PRIO);
		task_assert((int)( rc == 1), test_name, 
			     "got wrong effective prio of self", rc);

		/* Tests:
		 * 1. prio set ILLEGAL_ELEM
		 * 2. prio set nonexisting task
		 * 3. prio set same as existing prio 
		 * 4. prio set on task holding mutex 
		 * 5. prio set to prio that is in use
		 * 6. prio set to effective priority
		 */
		rc = os_prio_set(ILLEGAL_ELEM, 0);
		task_assert((int)( rc == ERR_NOSUCHTASK), test_name, 
			     "set prio of illegal task", rc);

		rc = os_prio_set(TIROS_MAX_PROCS-1, 0);
		task_assert((int)( rc == ERR_NOSUCHTASK), test_name, 
			     "set prio of nonexistent task", rc);
		
		rc = os_prio_set(Ttid[0], os_prio_get(Ttid[0], 0));
		task_assert((int)( rc == SUCCESS), test_name, 
			     "failed set prio of self to same", rc);


		rc = os_prio_set(Ttid[2], os_prio_get(Ttid[1], 0));
		task_assert((int)( rc == ERR_PRIO_IN_USE), test_name, 
			     "set prio of task to existing prio", rc);

		t1_orig_prio = os_prio_get(Ttid[1], 0);
		task_assert((int)( rc != ILLEGAL_ELEM), test_name,
			     "get prio of T1 failed", rc);


		/* Modify priority of Task 1, which is in the ready Q */
		rc = os_prio_set(Ttid[1], PRIO_TEST_T1_TMP  );
		task_assert((int)(rc == SUCCESS), test_name,
			    "set prio of T1 failed", rc);


		(void) csem_P(&prio_test_t2_t0, 0, 0);

		/* Modify priority of TAsk 1, which is now in the wait
		   Q */
		rc = os_prio_set(Ttid[1], t1_orig_prio  );
		task_assert((int)(rc == SUCCESS), test_name,
			    "set prio of T1 failed" , rc);

		t2_orig_prio = os_prio_get(Ttid[2], 0);
		task_assert((int)( rc != ILLEGAL_ELEM), test_name,
			     "get prio of T2 failed", rc);
		
		/* Set prio of T2, which owns a mutex.  */
		rc = os_prio_set(Ttid[2], PRIO_TEST_T2_TMP  );

		task_assert((int)(rc == ERR_WOULDBLOCK_MUTEX), test_name,
			    "set prio of task holding mutex", rc);

		(void) csem_P(&prio_test_t2_t0, 0, 0);

		/* Set prio of T2 back to its original */
		rc = os_prio_set(Ttid[2], t2_orig_prio );
		task_assert((int)(rc == SUCCESS), test_name,
			    "os_prio_set failed", rc);

	} else if (taskid == Ttid[1]) {
		

	} else if (taskid == Ttid[2]) {
		mutex_init(&prio_test_tmp , M_PRIO_TEST_TMP);
		/* Hold a mutex */
		rc = mutex_lock(&prio_test_tmp, 0, 0);
		task_assert((int)(rc == SUCCESS), test_name,
			    "mutex_lock failed", rc);

		(void) csem_V(&prio_test_t2_t0);
		
		rc = mutex_unlock(&prio_test_tmp);
		task_assert((int)(rc == SUCCESS), test_name,
			    "mutex_unlock failed", rc);

		(void)csem_V(&prio_test_t2_t0);
		
	} else if (taskid == Ttid[3]) {

		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V_0 failed", rc);

	}
}


static void isr_prio_test(int action)
{
	(void) action;
}


#define ISR_TIME_TEST1  0x01

static void isr_time_test(int action)
{
	static char const * const test_name = "isr_time_test";
	int16_t rc;
	trtime_t waketime;
	
	switch(action) {
	case ISR_TIME_TEST1:
		secs_to_trtime(2LU, &waketime);
		rc = os_wake_at(&waketime, O_RELATIVE_TIME);
		task_assert((int)(rc == ERR_WOULDBLOCK_ISR), test_name,
			    "bad retval for os_wake_at from isr", rc);
		break;

	default:
		task_assert(0, test_name, "bad action", (int16_t) action);
		break;
	}



}




static void time_test(tid_t taskid)
{
	static char const * const test_name = "time_test";
	int16_t rc;
	uint32_t secs_to_convert = 2;
	uint32_t converted_secs;
	trtime_t tmptime;
	
	if (taskid == Ttid[0]) {
		call_ISR(TIME_TEST, ISR_TIME_TEST1);

		secs_to_trtime(secs_to_convert, &tmptime);
		converted_secs = trtime_to_secs(&tmptime);
		task_assert((int)(converted_secs == secs_to_convert),
			    test_name, "time_conversion error", (short)converted_secs);
		
		/* Set time */
		tmptime.subunits = 0;
		tmptime.units = 0;
		(void)os_time_set(&tmptime);
		/* this may either fail or succeed depending on the
		   hardware platform */

		secs_to_convert = 10LU;
		secs_to_trtime(secs_to_convert, &tmptime);
		rc = os_wake_at(&tmptime, O_RELATIVE_TIME);
		task_assert((int)(rc == ERR_RESUMED), test_name,
			    "task was not resumed from wake", rc);
			
		
	} else if (taskid == Ttid[1]) {
		rc = os_task_resume(Ttid[0]);
		task_assert((int)(rc == SUCCESS), test_name,
			    "could not resume task 0", rc);

	} else if (taskid == Ttid[2]) {

	} else if (taskid == Ttid[3]) {

		rc = csem_V(&synchro_cs);
		task_assert((int)(rc == 1), test_name,
			    "V_0 failed", rc);

	}
}




